/*
 * Copyright 2020-2021 redragon.dongbin
 *
 * This file is part of redragon-erp/赤龙ERP.

 * redragon-erp/赤龙ERP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * redragon-erp/赤龙ERP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with redragon-erp/赤龙ERP.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.erp.ledger.je.service.spring;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.redragon.framework.annotation.Cache;
import org.redragon.framework.annotation.Cache.CacheType;
import org.redragon.framework.annotation.Log;
import org.redragon.framework.hibernate.data.SnowFlake;
import org.redragon.framework.hibernate.model.Pages;

import com.erp.ledger.balance.dao.model.GLBalance;
import com.erp.ledger.balance.service.GLBalanceService;
import com.erp.ledger.je.dao.GLJeHeadDao;
import com.erp.ledger.je.dao.GLJeLineDao;
import com.erp.ledger.je.dao.model.GLJeHead;
import com.erp.ledger.je.dao.model.GLJeHeadCO;
import com.erp.ledger.je.dao.model.GLJeLine;
import com.erp.ledger.je.service.GLJeHeadService;

@Service
@Transactional(rollbackFor=Exception.class)
public class GLJeHeadServiceImpl implements GLJeHeadService {

    //注入Dao
    @Autowired
    private GLJeHeadDao gLJeHeadDao;
    @Autowired
    private GLJeLineDao glJeLineDao;
    @Autowired
    private GLBalanceService glBalanceService;
    
    @Override
    public void insertDataObject(GLJeHead obj) {
        this.gLJeHeadDao.insertDataObject(obj);
    }

    @Override
    public void updateDataObject(GLJeHead obj) {
        this.gLJeHeadDao.updateDataObject(obj);
    }
    
    @Override
    public void insertOrUpdateDataObject(GLJeHead obj) {
        this.gLJeHeadDao.insertOrUpdateDataObject(obj);
    }

    @Override
    public void deleteDataObject(GLJeHead obj) {
        this.gLJeHeadDao.deleteDataObject(obj);
        this.glJeLineDao.deleteGLJeLineByHeadCode(obj.getJeHeadCode());
    }

    @Override
    public List<GLJeHead> getDataObjects() {
        return this.gLJeHeadDao.getDataObjects();
    }

    @Override
    public GLJeHead getDataObject(int id) {
        return this.gLJeHeadDao.getDataObject(id);
    }

    @Override
    public GLJeHead getDataObject(String code) {
        return this.gLJeHeadDao.getDataObject(code);
    }

    @Override
    public List<GLJeHead> getDataObjects(GLJeHeadCO paramObj) {
        return this.gLJeHeadDao.getDataObjects(paramObj);
    }

    @Override
    public List<GLJeHead> getDataObjects(Pages pages) {
        return this.gLJeHeadDao.getDataObjects(pages);
    }
    
    @Override
    public List<GLJeHead> getDataObjects(Pages pages, GLJeHeadCO paramObj) {
        return this.gLJeHeadDao.getDataObjects(pages, paramObj);
    }
    
    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, GLJeHeadCO paramObj) {
        return this.gLJeHeadDao.getDataObjectsArray(pages, paramObj);
    }
    
    @Override
    public List<GLJeHead> getDataObjectsForDataAuth(String dataAuthSQL, Pages pages, GLJeHeadCO paramObj) {
        return this.gLJeHeadDao.getDataObjectsForDataAuth(dataAuthSQL, pages, paramObj);
    }
    
    @Override
    @Cache(cacheType=CacheType.ALL, cacheSeconds=7200)
    public int getHeadNum(String startDate, String endDate) {
        return this.gLJeHeadDao.getHeadNum(startDate, endDate);
    }
    
    @Override
    public void insertOrUpdateGLJe(GLJeHead glJeHead, List<GLJeLine> glJeLineList) {
        //编辑头
        this.gLJeHeadDao.insertOrUpdateDataObject(glJeHead);
        //循环编辑行
        for(GLJeLine glJeLine: glJeLineList) {
            this.glJeLineDao.insertOrUpdateDataObject(glJeLine);
        }
    }
    
    @Override
    public void updateHeadForApproveStatus(Integer headId, String approveStatus) {
        this.gLJeHeadDao.updateHeadForApproveStatus(headId, approveStatus);
    }
    
    @Override
    public void updateHeadForStatus(Integer headId, String status) {
        this.gLJeHeadDao.updateHeadForStatus(headId, status);
    }
    
    @Override
    public List<GLJeHead> getGLJeHeadPostListByIds(String headIds) {
        return this.gLJeHeadDao.getGLJeHeadPostListByIds(headIds);
    }
    
    @Override
    public List<GLJeHead> getGLJeHeadPostListByPeriodName(String periodName) {
        return this.gLJeHeadDao.getGLJeHeadPostListByPeriodName(periodName);
    }
    
    @Override
    public String reverseJe(Integer headId, String periodName) {
        try {
            //获取日记账头信息
            GLJeHead glJeHead = this.gLJeHeadDao.getDataObject(headId);
            
            //获取日记账行信息
            List<GLJeLine> glJeLineList = this.glJeLineDao.getGLJeLineListByHeadCode(glJeHead.getJeHeadCode());
            
            //复制冲销日记账头
            GLJeHead glJeHeadR = new GLJeHead();
            glJeHeadR.setJeHeadCode(SnowFlake.getConcurrentId().toString());
            glJeHeadR.setJeName("冲销 "+glJeHead.getJeName());
            glJeHeadR.setJeSource(glJeHead.getJeSource());
            glJeHeadR.setJeType(glJeHead.getJeType());
            glJeHeadR.setJeDate(glJeHead.getJeDate());
            glJeHeadR.setJeDesc("冲销日记账，原日记账编码："+glJeHead.getJeHeadCode());
            glJeHeadR.setBillNum(glJeHead.getBillNum());
            glJeHeadR.setLedgerCode(glJeHead.getLedgerCode());
            glJeHeadR.setPeriodName(periodName);
            glJeHeadR.setCurrencyCode(glJeHead.getCurrencyCode());
            glJeHeadR.setStaffCode(glJeHead.getStaffCode());
            glJeHeadR.setDepartmentCode(glJeHead.getDepartmentCode());
            //创建冲销日记账头
            this.gLJeHeadDao.insertDataObject(glJeHeadR);
            
            //复制冲销日记账行
            for(GLJeLine glJeLine: glJeLineList) {
                GLJeLine glJeLineR = new GLJeLine();
                glJeLineR.setJeHeadCode(glJeHeadR.getJeHeadCode());
                glJeLineR.setJeLineCode(SnowFlake.getConcurrentId().toString());
                glJeLineR.setMemo(glJeLine.getMemo());
                glJeLineR.setSubjectCode(glJeLine.getSubjectCode());
                glJeLineR.setCrAmount(-glJeLine.getCrAmount());
                glJeLineR.setDrAmount(-glJeLine.getDrAmount());
                //创建冲销日记账行
                this.glJeLineDao.insertDataObject(glJeLineR);
            }
            
            //将创建的冲销日记账编码存入原始的日记账
            glJeHead.setReverseJeHeadCode(glJeHeadR.getJeHeadCode());
            glJeHead.setStatus("REVERSE");
            this.gLJeHeadDao.updateDataObject(glJeHead);
            
            return "冲销日记账已自动生成，日记账编码："+glJeHeadR.getJeHeadCode();
        }catch(Exception e) {
            return "冲销日记账创建失败";
        }
    }
    
    @Override
    public String postJeToGL(Integer headId) {
        //获取日记账头信息
        GLJeHead glJeHead = this.gLJeHeadDao.getDataObject(headId);
        
        //获取日记账行信息
        List<GLJeLine> glJeLineList = this.glJeLineDao.getGLJeLineListByHeadCode(glJeHead.getJeHeadCode());
        
        //循环日记账行
        for(GLJeLine glJeLine: glJeLineList) {
            //根据科目获取已存在的科目余额表中的最后一行
            GLBalance lastBalance = this.glBalanceService.getLastGLBalanceBySubject(glJeHead.getLedgerCode(), glJeLine.getSubjectCode());
            //计算新余额行的期初
            Double begin = 0D;
            Double lastLedgerDr = 0D;
            Double lastLedgerCr = 0D;
            if(lastBalance!=null) {
                begin = new BigDecimal(lastBalance.getBeginDr()).subtract(new BigDecimal(lastBalance.getBeginCr()))
                        .add(new BigDecimal(lastBalance.getPeriodDr())).subtract(new BigDecimal(lastBalance.getPeriodCr())).doubleValue();
                lastLedgerDr = lastBalance.getLedgerDr();
                lastLedgerCr = lastBalance.getLedgerCr();
            }
            
            
            //创建新科目余额
            GLBalance glBalance = new GLBalance();
            glBalance.setActualFlag("Y");
            glBalance.setStatus("Y");
            glBalance.setBalanceCode(SnowFlake.getConcurrentId().toString());
            glBalance.setLedgerCode(glJeHead.getLedgerCode());
            glBalance.setCurrencyCode(glJeHead.getCurrencyCode());
            glBalance.setPeriodName(glJeHead.getPeriodName());
            glBalance.setSubjectCode(glJeLine.getSubjectCode());
            glBalance.setJeHeadCode(glJeHead.getJeHeadCode());
            glBalance.setJeLineCode(glJeLine.getJeLineCode());
            glBalance.setPeriodDr(glJeLine.getDrAmount());
            glBalance.setPeriodCr(glJeLine.getCrAmount());
            glBalance.setBeginDr(0D);
            glBalance.setBeginCr(0D);
            if(begin>=0) {
                glBalance.setBeginDr(begin);
            }else {
                glBalance.setBeginCr(-begin);
            }
            glBalance.setLedgerDr(new BigDecimal(lastLedgerDr).add(new BigDecimal(glJeLine.getDrAmount())).doubleValue());
            glBalance.setLedgerCr(new BigDecimal(lastLedgerCr).add(new BigDecimal(glJeLine.getCrAmount())).doubleValue());
            glBalance.setQuarterCr(0D);
            glBalance.setQuarterDr(0D);

            this.glBalanceService.insertDataObject(glBalance);
        }
        
        //修改过账状态
        this.gLJeHeadDao.updateJePostStatus(headId);
        return "过账完成";
    }
    
    @Override
    public int getJeNumByStatus(String status, String approveStatus, String postStatus, String periodName) {
        return this.gLJeHeadDao.getJeNumByStatus(status, approveStatus, postStatus, periodName);
    }
    
}